import "core-js/modules/es.error.cause.js";
import "core-js/modules/esnext.iterator.constructor.js";
import "core-js/modules/esnext.iterator.for-each.js";
import "core-js/modules/esnext.iterator.map.js";
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
import { BasePlugin } from "../base/index.mjs";
import { clamp } from "../../helpers/number.mjs";
import { getScrollbarWidth } from "../../helpers/dom/element.mjs";
import { PaginationUI } from "./ui.mjs";
import { checkPluginSettingsConflict } from "./utils.mjs";
import { announce } from "../../utils/a11yAnnouncer.mjs";
import { createPaginatorStrategy } from "./strategies/index.mjs";
import { toSingleLine } from "../../helpers/templateLiteralTag.mjs";
import { warn } from "../../helpers/console.mjs";
import { createPaginationFocusController } from "./focusController.mjs";
import { installFocusDetector } from "../../utils/focusDetector.mjs";
export const PLUGIN_KEY = 'pagination';
export const PLUGIN_PRIORITY = 900;
const SHORTCUTS_GROUP = PLUGIN_KEY;
const SHORTCUTS_CONTEXT_NAME = `plugin:${PLUGIN_KEY}`;
const AUTO_PAGE_SIZE_WARNING = toSingleLine`The \`auto\` page size setting requires the \`autoRowSize\`\x20
  plugin to be enabled. Set the \`autoRowSize: true\` in the configuration to ensure correct behavior.`;

/* eslint-disable jsdoc/require-description-complete-sentence */
/**
 * @plugin Pagination
 * @class Pagination
 *
 * @description
 * The plugin adds full-featured pagination capabilities to a table component.
 * It manages splitting rows into pages, rendering navigation controls, and exposing
 * methods and configuration for initializing and updating pagination state.
 *
 * Core responsibilities:
 *  - Calculate which rows should be visible based on current `page` and `pageSize`.
 *  - Render a toolbar area containing:
 *    - a page size dropdown section (if `showPageSize` = `true`)
 *    - a row counter section ("1 - 10 of 50", if `showCounter` = `true`)
 *    - page navigation section (if `showNavigation` = `true`)
 *  - Emit hooks when:
 *    - the user navigates to a different page
 *    - the user changes the number of rows per page
 *    - the user changes the visibility of any sections
 *  - Allow external code to programmatically:
 *    - jump to a specific page
 *    - change the page size
 *    - change the visibility of UI sections
 *
 * @example
 *
 * ::: only-for javascript
 * ```js
 * const hot = new Handsontable(document.getElementById('example'), {
 *   data: getData(),
 *   pagination: {
 *     pageSize: 10,
 *     pageSizeList: ['auto', 5, 10, 20, 50, 100],
 *     initialPage: 1,
 *     showPageSize: true,
 *     showCounter: true,
 *     showNavigation: true,
 *  },
 * });
 * ```
 * :::
 *
 * ::: only-for react
 * ```jsx
 * <HotTable
 *   data={getData()}
 *   pagination={{
 *     pageSize: 10,
 *     pageSizeList: ['auto', 5, 10, 20, 50, 100],
 *     initialPage: 1,
 *     showPageSize: true,
 *     showCounter: true,
 *     showNavigation: true,
 *   }}
 * />
 * ```
 * :::
 *
 * ::: only-for angular
 * ```ts
 * settings = {
 *   pagination: {
 *     pageSize: 10,
 *     pageSizeList: ['auto', 5, 10, 20, 50, 100],
 *     initialPage: 1,
 *     showPageSize: true,
 *     showCounter: true,
 *     showNavigation: true,
 *   },
 * };
 * ```
 * :::
 */
var _pagedRowsMap = /*#__PURE__*/new WeakMap();
var _currentPage = /*#__PURE__*/new WeakMap();
var _pageSize = /*#__PURE__*/new WeakMap();
var _ui = /*#__PURE__*/new WeakMap();
var _calcStrategy = /*#__PURE__*/new WeakMap();
var _internalExecutionCall = /*#__PURE__*/new WeakMap();
var _internalRenderCall = /*#__PURE__*/new WeakMap();
var _focusController = /*#__PURE__*/new WeakMap();
var _focusDetector = /*#__PURE__*/new WeakMap();
var _Pagination_brand = /*#__PURE__*/new WeakSet();
var _onIndexCacheUpdate = /*#__PURE__*/new WeakMap();
export class Pagination extends BasePlugin {
  constructor() {
    super(...arguments);
    /**
     * Bind the events used by the plugin.
     */
    _classPrivateMethodInitSpec(this, _Pagination_brand);
    /**
     * Map of hidden rows controlled by the pagination plugin.
     *
     * @type {HiddenMap | null}
     */
    _classPrivateFieldInitSpec(this, _pagedRowsMap, null);
    /**
     * Current page number.
     *
     * @type {number}
     */
    _classPrivateFieldInitSpec(this, _currentPage, 1);
    /**
     * Page size setup by the user. It can be a number or 'auto' (in which case the plugin will
     * calculate the page size based on the viewport size and row heights).
     *
     * @type {number | 'auto'}
     */
    _classPrivateFieldInitSpec(this, _pageSize, 10);
    /**
     * UI instance of the pagination plugin.
     *
     * @type {PaginationUI}
     */
    _classPrivateFieldInitSpec(this, _ui, null);
    /**
     * Pagination calculation strategy instance. It is used to calculate the pagination state
     * based on the user-defined settings. The result of the state is used to update the
     * pagination index mapper.
     *
     * @type {AutoPageSizeStrategy | FixedPageSizeStrategy | null}
     */
    _classPrivateFieldInitSpec(this, _calcStrategy, null);
    /**
     * Flag indicating if the plugin is in the process of updating the index cache (execution operation).
     * Prevents circular calls when the index cache is updated.
     *
     * @type {boolean}
     */
    _classPrivateFieldInitSpec(this, _internalExecutionCall, false);
    /**
     * Flag indicating if the plugin is in the process of updating the internal state (render operation).
     * Prevents circular calls when the render call is triggered by the pagination plugin itself.
     *
     * @type {boolean}
     */
    _classPrivateFieldInitSpec(this, _internalRenderCall, false);
    /**
     * Pagination focus controller instance.
     *
     * @type {PaginationController}
     */
    _classPrivateFieldInitSpec(this, _focusController, null);
    /**
     * Pagination focus detector instance.
     *
     * @type {object}
     */
    _classPrivateFieldInitSpec(this, _focusDetector, null);
    /**
     * IndexMapper cache update listener. Once the cache is updated, we need to recompute
     * the pagination state.
     *
     * The method uses arrow function to keep the reference to the class method. Necessary for
     * the `removeLocalHook` method of the row index mapper.
     */
    _classPrivateFieldInitSpec(this, _onIndexCacheUpdate, () => {
      var _this$hot;
      if (!_classPrivateFieldGet(_internalExecutionCall, this) && (_this$hot = this.hot) !== null && _this$hot !== void 0 && _this$hot.view) {
        _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
      }
    });
  }
  static get PLUGIN_KEY() {
    return PLUGIN_KEY;
  }
  static get PLUGIN_PRIORITY() {
    return PLUGIN_PRIORITY;
  }
  static get DEFAULT_SETTINGS() {
    return {
      pageSize: 10,
      pageSizeList: ['auto', 5, 10, 20, 50, 100],
      initialPage: 1,
      showPageSize: true,
      showCounter: true,
      showNavigation: true,
      uiContainer: null
    };
  }
  /**
   * Checks if the plugin is enabled in the handsontable settings. This method is executed in {@link Hooks#beforeInit}
   * hook and if it returns `true` than the {@link Pagination#enablePlugin} method is called.
   *
   * @returns {boolean}
   */
  isEnabled() {
    return !!this.hot.getSettings()[PLUGIN_KEY];
  }

  /**
   * Enables the plugin functionality for this Handsontable instance.
   */
  enablePlugin() {
    var _this$hot$getPlugin,
      _this = this;
    if (checkPluginSettingsConflict(this.hot.getSettings())) {
      this.hot.getSettings()[PLUGIN_KEY] = false;
      return;
    }
    if (this.enabled) {
      return;
    }
    const settings = this.hot.getSettings()[PLUGIN_KEY];
    if ((settings === null || settings === void 0 ? void 0 : settings.initialPage) !== undefined) {
      _classPrivateFieldSet(_currentPage, this, this.getSetting('initialPage'));
    }
    if ((settings === null || settings === void 0 ? void 0 : settings.pageSize) !== undefined) {
      _classPrivateFieldSet(_pageSize, this, this.getSetting('pageSize'));
    }
    _classPrivateFieldSet(_pagedRowsMap, this, this.hot.rowIndexMapper.createAndRegisterIndexMap(this.pluginName, 'hiding', false));
    if (_classPrivateFieldGet(_pageSize, this) === 'auto' && !((_this$hot$getPlugin = this.hot.getPlugin('autoRowSize')) !== null && _this$hot$getPlugin !== void 0 && _this$hot$getPlugin.enabled)) {
      warn(AUTO_PAGE_SIZE_WARNING);
    }
    _classPrivateFieldSet(_calcStrategy, this, createPaginatorStrategy(_classPrivateFieldGet(_pageSize, this) === 'auto' ? 'auto' : 'fixed'));
    if (!_classPrivateFieldGet(_ui, this)) {
      _classPrivateFieldSet(_ui, this, new PaginationUI({
        rootElement: this.hot.rootGridElement,
        uiContainer: this.getSetting('uiContainer'),
        isRtl: this.hot.isRtl(),
        themeName: this.hot.getSettings().themeName,
        phraseTranslator: function () {
          return _this.hot.getTranslatedPhrase(...arguments);
        },
        shouldHaveBorder: () => _assertClassBrand(_Pagination_brand, this, _computeNeedsBorder).call(this),
        a11yAnnouncer: message => announce(message)
      }));
      _assertClassBrand(_Pagination_brand, this, _updateSectionsVisibilityState).call(this);
      _classPrivateFieldGet(_ui, this).addLocalHook('firstPageClick', () => this.firstPage()).addLocalHook('prevPageClick', () => this.prevPage()).addLocalHook('nextPageClick', () => this.nextPage()).addLocalHook('lastPageClick', () => this.lastPage()).addLocalHook('pageSizeChange', pageSize => this.setPageSize(pageSize)).addLocalHook('focus', element => {
        _classPrivateFieldGet(_focusController, this).setCurrentPage(_classPrivateFieldGet(_ui, this).getFocusableElements().indexOf(element));
        this.hot.unlisten();
        this.hot.getShortcutManager().setActiveContextName(SHORTCUTS_CONTEXT_NAME);
        this.hot.listen();
        _classPrivateFieldGet(_focusDetector, this).deactivate();
      });
    }
    if (!_classPrivateFieldGet(_focusController, this)) {
      _classPrivateFieldSet(_focusController, this, createPaginationFocusController({
        focusableElements: () => _classPrivateFieldGet(_ui, this).getFocusableElements()
      }));
    }
    if (!_classPrivateFieldGet(_focusDetector, this)) {
      _classPrivateFieldSet(_focusDetector, this, installFocusDetector(this.hot, _classPrivateFieldGet(_ui, this).getContainer(), {
        onFocus: from => {
          this.hot.getShortcutManager().setActiveContextName(SHORTCUTS_CONTEXT_NAME);
          this.hot.listen();
          if (from === 'from_above') {
            _classPrivateFieldGet(_focusController, this).toFirstItem();
          } else {
            _classPrivateFieldGet(_focusController, this).toLastItem();
          }
          _classPrivateFieldGet(_focusDetector, this).deactivate();
        }
      }));
    }
    _assertClassBrand(_Pagination_brand, this, _registerEvents).call(this);
    _assertClassBrand(_Pagination_brand, this, _registerShortcuts).call(this);

    // Place the onInit hook before others to make sure that the pagination state is computed
    // and applied to the index mapper before AutoColumnSize plugin begins calculate the column sizes.
    this.addHook('init', function () {
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onInit).call(_this, ...args);
    }, -1);
    this.addHook('beforeSelectAll', function () {
      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforeSelectAllRows).call(_this, ...args);
    });
    this.addHook('beforeSelectColumns', function () {
      for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
        args[_key3] = arguments[_key3];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforeSelectAllRows).call(_this, ...args);
    });
    this.addHook('beforeSetRangeEnd', function () {
      for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
        args[_key4] = arguments[_key4];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforeSetRangeEnd).call(_this, ...args);
    });
    this.addHook('beforeSelectionHighlightSet', function () {
      for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
        args[_key5] = arguments[_key5];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforeSelectionHighlightSet).call(_this, ...args);
    });
    this.addHook('beforePaste', function () {
      for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
        args[_key6] = arguments[_key6];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforePaste).call(_this, ...args);
    });
    this.addHook('afterViewRender', function () {
      for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
        args[_key7] = arguments[_key7];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterViewRender).call(_this, ...args);
    });
    this.addHook('afterRender', function () {
      for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
        args[_key8] = arguments[_key8];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterRender).call(_this, ...args);
    });
    this.addHook('afterScrollVertically', function () {
      for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
        args[_key9] = arguments[_key9];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterScrollVertically).call(_this, ...args);
    });
    this.addHook('afterLanguageChange', function () {
      for (var _len0 = arguments.length, args = new Array(_len0), _key0 = 0; _key0 < _len0; _key0++) {
        args[_key0] = arguments[_key0];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterLanguageChange).call(_this, ...args);
    });
    this.addHook('modifyRowHeight', function () {
      for (var _len1 = arguments.length, args = new Array(_len1), _key1 = 0; _key1 < _len1; _key1++) {
        args[_key1] = arguments[_key1];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onModifyRowHeight).call(_this, ...args);
    });
    this.addHook('beforeHeightChange', function () {
      for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
        args[_key10] = arguments[_key10];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onBeforeHeightChange).call(_this, ...args);
    });
    this.addHook('afterSetTheme', function () {
      for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) {
        args[_key11] = arguments[_key11];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterSetTheme).call(_this, ...args);
    });
    this.addHook('afterDialogShow', function () {
      for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) {
        args[_key12] = arguments[_key12];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterDialogShow).call(_this, ...args);
    });
    this.addHook('beforeDialogHide', function () {
      for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) {
        args[_key13] = arguments[_key13];
      }
      return _assertClassBrand(_Pagination_brand, _this, _onAfterDialogHide).call(_this, ...args);
    });
    this.hot.rowIndexMapper.addLocalHook('cacheUpdated', _classPrivateFieldGet(_onIndexCacheUpdate, this));
    super.enablePlugin();
  }

  /**
   * Updates the plugin state. This method is executed when {@link Core#updateSettings} is invoked.
   */
  updatePlugin() {
    this.disablePlugin();
    this.enablePlugin();
    _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
    super.updatePlugin();
  }

  /**
   * Disables the plugin functionality for this Handsontable instance.
   */
  disablePlugin() {
    this.hot.rowIndexMapper.removeLocalHook('cacheUpdated', _classPrivateFieldGet(_onIndexCacheUpdate, this)).unregisterMap(this.pluginName);
    _classPrivateFieldGet(_ui, this).destroy();
    _classPrivateFieldSet(_ui, this, null);
    _assertClassBrand(_Pagination_brand, this, _unregisterShortcuts).call(this);
    super.disablePlugin();
  }
  /**
   * Gets the pagination current state. Returns an object with the following properties:
   *  - `currentPage`: The current page number.
   *  - `totalPages`: The total number of pages.
   *  - `pageSize`: The page size.
   *  - `pageSizeList`: The list of page sizes.
   *  - `autoPageSize`: Whether the page size is calculated automatically.
   *  - `numberOfRenderedRows`: The number of rendered rows.
   *  - `firstVisibleRowIndex`: The index of the first visible row.
   *  - `lastVisibleRowIndex`: The index of the last visible row.
   *
   * @returns {{
   *   currentPage: number,
   *   totalPages: number,
   *   pageSize: number,
   *   pageSizeList: Array<number | 'auto'>,
   *   autoPageSize: boolean,
   *   numberOfRenderedRows: number,
   *   firstVisibleRowIndex: number,
   *   lastVisibleRowIndex: number
   * }}
   */
  getPaginationData() {
    const totalPages = _classPrivateFieldGet(_calcStrategy, this).getTotalPages();
    let firstVisibleRowIndex = -1;
    let lastVisibleRowIndex = -1;
    const {
      pageSize,
      startIndex
    } = _classPrivateFieldGet(_calcStrategy, this).getState(_classPrivateFieldGet(_currentPage, this));
    const countRows = this.hot.countRows();
    let visibleCount = 0;
    for (let rowIndex = startIndex; visibleCount < pageSize; rowIndex++) {
      if (rowIndex >= countRows) {
        break;
      }
      if (this.hot.rowIndexMapper.isHidden(this.hot.toPhysicalRow(rowIndex))) {
        // eslint-disable-next-line no-continue
        continue;
      }
      if (firstVisibleRowIndex === -1) {
        firstVisibleRowIndex = rowIndex;
      }
      lastVisibleRowIndex = rowIndex;
      visibleCount += 1;
    }
    return {
      currentPage: _classPrivateFieldGet(_currentPage, this),
      totalPages,
      pageSize,
      pageSizeList: [...this.getSetting('pageSizeList')],
      autoPageSize: _classPrivateFieldGet(_pageSize, this) === 'auto',
      numberOfRenderedRows: this.hot.rowIndexMapper.getRenderableIndexesLength(),
      firstVisibleRowIndex,
      lastVisibleRowIndex
    };
  }

  /**
   * Allows changing the page for specified page number.
   *
   * @param {number} pageNumber The page number to set (from 1 to N). If `0` is passed, it
   * will be transformed to `1`.
   * @fires Hooks#beforePageChange
   * @fires Hooks#afterPageChange
   */
  setPage(pageNumber) {
    const oldPage = _classPrivateFieldGet(_currentPage, this);
    const shouldProceed = this.hot.runHooks('beforePageChange', oldPage, pageNumber);
    if (shouldProceed === false) {
      return;
    }
    _classPrivateFieldSet(_currentPage, this, pageNumber);
    _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
    this.hot.scrollViewportTo({
      row: 0
    });
    this.hot.runHooks('afterPageChange', oldPage, _classPrivateFieldGet(_currentPage, this));
    this.hot.view.adjustElementsSize();
    this.hot.render();
  }

  /**
   * Resets the current page to the initial page (`initialValue`) defined in the settings.
   */
  resetPage() {
    this.setPage(this.getSetting('initialPage'));
  }

  /**
   * Changes the page size for the pagination. The method recalculates the state based
   * on the new page size and re-renders the table. If `'auto'` is passed, the plugin will
   * calculate the page size based on the viewport size and row heights to make sure
   * that there will be no vertical scrollbar in the table.
   *
   * @param {number | 'auto'} pageSize The page size to set.
   * @fires Hooks#beforePageSizeChange
   * @fires Hooks#afterPageSizeChange
   */
  setPageSize(pageSize) {
    var _this$hot$getPlugin2;
    const oldPageSize = _classPrivateFieldGet(_pageSize, this);
    const shouldProceed = this.hot.runHooks('beforePageSizeChange', oldPageSize, pageSize);
    if (shouldProceed === false) {
      return;
    }
    if (pageSize === 'auto' && !((_this$hot$getPlugin2 = this.hot.getPlugin('autoRowSize')) !== null && _this$hot$getPlugin2 !== void 0 && _this$hot$getPlugin2.enabled)) {
      warn(AUTO_PAGE_SIZE_WARNING);
    }
    _classPrivateFieldSet(_calcStrategy, this, createPaginatorStrategy(pageSize === 'auto' ? 'auto' : 'fixed'));
    _classPrivateFieldSet(_pageSize, this, pageSize);
    _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
    this.hot.runHooks('afterPageSizeChange', oldPageSize, _classPrivateFieldGet(_pageSize, this));
    this.hot.view.adjustElementsSize();
    this.hot.render();
  }

  /**
   * Resets the page size to the initial value (`pageSize`) defined in the settings.
   */
  resetPageSize() {
    this.setPageSize(this.getSetting('pageSize'));
  }

  /**
   * Resets the pagination state to the initial values defined in the settings.
   */
  resetPagination() {
    this.resetPage();
    this.resetPageSize();
    _assertClassBrand(_Pagination_brand, this, _updateSectionsVisibilityState).call(this);
  }

  /**
   * Switches the page to the next one.
   */
  nextPage() {
    this.setPage(_classPrivateFieldGet(_currentPage, this) + 1);
  }

  /**
   * Switches the page to the previous one.
   */
  prevPage() {
    this.setPage(_classPrivateFieldGet(_currentPage, this) - 1);
  }

  /**
   * Switches the page to the first one.
   */
  firstPage() {
    this.setPage(1);
  }

  /**
   * Switches the page to the last one.
   */
  lastPage() {
    this.setPage(_classPrivateFieldGet(_calcStrategy, this).getTotalPages());
  }

  /**
   * Checks, based on the current internal state, if there is a previous page.
   *
   * @returns {boolean}
   */
  hasPreviousPage() {
    return _classPrivateFieldGet(_currentPage, this) > 1;
  }

  /**
   * Checks, based on the current internal state, if there is a next page.
   *
   * @returns {boolean}
   */
  hasNextPage() {
    return _classPrivateFieldGet(_currentPage, this) < _classPrivateFieldGet(_calcStrategy, this).getTotalPages();
  }

  /**
   * Gets the visual data for the current page. The returned data may be longer than the defined
   * page size as the data may contain hidden rows (rows that are not rendered in the table).
   *
   * @returns {Array<Array>} Returns the data for the current page.
   */
  getCurrentPageData() {
    const {
      firstVisibleRowIndex,
      lastVisibleRowIndex
    } = this.getPaginationData();
    if (firstVisibleRowIndex === -1 || lastVisibleRowIndex === -1) {
      return [];
    }
    return this.hot.getData(firstVisibleRowIndex, 0, lastVisibleRowIndex, this.hot.countCols() - 1);
  }

  /**
   * Shows the page size section in the pagination UI.
   *
   * @fires Hooks#afterPageSizeVisibilityChange
   */
  showPageSizeSection() {
    _classPrivateFieldGet(_ui, this).setPageSizeSectionVisibility(true);
    this.hot.runHooks('afterPageSizeVisibilityChange', true);
  }

  /**
   * Hides the page size section in the pagination UI.
   *
   * @fires Hooks#afterPageSizeVisibilityChange
   */
  hidePageSizeSection() {
    _classPrivateFieldGet(_ui, this).setPageSizeSectionVisibility(false);
    this.hot.runHooks('afterPageSizeVisibilityChange', false);
  }

  /**
   * Shows the page counter section in the pagination UI.
   *
   * @fires Hooks#afterPageCounterVisibilityChange
   */
  showPageCounterSection() {
    _classPrivateFieldGet(_ui, this).setCounterSectionVisibility(true);
    this.hot.runHooks('afterPageCounterVisibilityChange', true);
  }

  /**
   * Hides the page counter section in the pagination UI.
   *
   * @fires Hooks#afterPageCounterVisibilityChange
   */
  hidePageCounterSection() {
    _classPrivateFieldGet(_ui, this).setCounterSectionVisibility(false);
    this.hot.runHooks('afterPageCounterVisibilityChange', false);
  }

  /**
   * Shows the page navigation section in the pagination UI.
   *
   * @fires Hooks#afterPageNavigationVisibilityChange
   */
  showPageNavigationSection() {
    _classPrivateFieldGet(_ui, this).setNavigationSectionVisibility(true);
    this.hot.runHooks('afterPageNavigationVisibilityChange', true);
  }

  /**
   * Hides the page navigation section in the pagination UI.
   *
   * @fires Hooks#afterPageNavigationVisibilityChange
   */
  hidePageNavigationSection() {
    _classPrivateFieldGet(_ui, this).setNavigationSectionVisibility(false);
    this.hot.runHooks('afterPageNavigationVisibilityChange', false);
  }

  /**
   * Updates the visibility state of the pagination sections based on the current settings.
   */

  /**
   * Destroys the plugin instance.
   */
  destroy() {
    var _classPrivateFieldGet2;
    _classPrivateFieldSet(_pagedRowsMap, this, null);
    _classPrivateFieldSet(_calcStrategy, this, null);
    (_classPrivateFieldGet2 = _classPrivateFieldGet(_ui, this)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.destroy();
    _classPrivateFieldSet(_ui, this, null);
    super.destroy();
  }
}
function _registerEvents() {
  // TODO: move to general focus manager module
  this.eventManager.addEventListener(this.hot.rootDocument, 'mouseup', event => {
    const container = _classPrivateFieldGet(_ui, this).getContainer();
    if (!container.contains(event.target) && this.hot.getShortcutManager().getActiveContextName() === SHORTCUTS_CONTEXT_NAME) {
      _classPrivateFieldGet(_focusDetector, this).activate();
      _classPrivateFieldGet(_focusController, this).clear();
      this.hot.getShortcutManager().setActiveContextName('grid');
    }
  });
}
/**
 * Register shortcuts responsible for navigating through the pagination.
 */
function _registerShortcuts() {
  var _manager$getContext;
  const manager = this.hot.getShortcutManager();
  const pluginContext = (_manager$getContext = manager.getContext(SHORTCUTS_CONTEXT_NAME)) !== null && _manager$getContext !== void 0 ? _manager$getContext : manager.addContext(SHORTCUTS_CONTEXT_NAME, 'global');
  pluginContext.addShortcut({
    keys: [['Shift', 'Tab'], ['Tab']],
    preventDefault: false,
    callback: event => {
      let previousIndex = _classPrivateFieldGet(_focusController, this).getCurrentPage();
      if (event.shiftKey) {
        _classPrivateFieldGet(_focusController, this).toPreviousItem();
        const currentPage = _classPrivateFieldGet(_focusController, this).getCurrentPage();
        if (currentPage >= previousIndex) {
          _assertClassBrand(_Pagination_brand, this, _unFocusPagination).call(this);
          return;
        }
        previousIndex = currentPage;
      } else {
        _classPrivateFieldGet(_focusController, this).toNextItem();
        const currentPage = _classPrivateFieldGet(_focusController, this).getCurrentPage();
        if (currentPage <= previousIndex) {
          _assertClassBrand(_Pagination_brand, this, _unFocusPagination).call(this);
          return;
        }
        previousIndex = currentPage;
      }
      event.preventDefault();
    },
    group: SHORTCUTS_GROUP
  });
}
/**
 * Unregister shortcuts responsible for navigating through the pagination.
 */
function _unregisterShortcuts() {
  const shortcutManager = this.hot.getShortcutManager();
  const pluginContext = shortcutManager.getContext(SHORTCUTS_CONTEXT_NAME);
  pluginContext.removeShortcutsByGroup(SHORTCUTS_GROUP);
}
function _updateSectionsVisibilityState() {
  if (this.getSetting('showPageSize')) {
    this.showPageSizeSection();
  } else {
    this.hidePageSizeSection();
  }
  if (this.getSetting('showCounter')) {
    this.showPageCounterSection();
  } else {
    this.hidePageCounterSection();
  }
  if (this.getSetting('showNavigation')) {
    this.showPageNavigationSection();
  } else {
    this.hidePageNavigationSection();
  }
}
/**
 * Applies the current pagination state to the internal index mapper and updates the UI.
 */
function _computeAndApplyState() {
  _classPrivateFieldSet(_internalExecutionCall, this, true);
  _classPrivateFieldGet(_pagedRowsMap, this).clear();
  const renderableIndexes = this.hot.rowIndexMapper.getRenderableIndexes();
  const renderableRowsLength = renderableIndexes.length;
  const {
    stylesHandler
  } = this.hot;
  _classPrivateFieldGet(_calcStrategy, this).calculate({
    pageSize: _classPrivateFieldGet(_pageSize, this),
    totalItems: renderableRowsLength,
    viewportSizeProvider: () => {
      const {
        view
      } = this.hot;
      if (view.isVerticallyScrollableByWindow()) {
        const bodyStyle = getComputedStyle(this.hot.rootDocument.body);
        const margin = Number.parseInt(bodyStyle.marginTop, 10) + Number.parseInt(bodyStyle.marginBottom, 10);
        const columnHeaderHeight = this.hot.hasColHeaders() ? view._wt.wtTable.getColumnHeaderHeight() : 0;
        const paginationContainerHeight = _classPrivateFieldGet(_ui, this).getHeight();
        const workspaceHeight = view.getWorkspaceHeight();
        return workspaceHeight - paginationContainerHeight - columnHeaderHeight - margin;
      }
      const scrollbarWidth = view.hasHorizontalScroll() ? getScrollbarWidth() : 0;
      return view.getViewportHeight() - scrollbarWidth;
    },
    itemsSizeProvider: () => {
      const defaultRowHeight = stylesHandler.getDefaultRowHeight();
      const rowHeights = this.hot.rowIndexMapper.getRenderableIndexes().map(physicalIndex => {
        var _this$hot$getRowHeigh;
        return (_this$hot$getRowHeigh = this.hot.getRowHeight(this.hot.toVisualRow(physicalIndex))) !== null && _this$hot$getRowHeigh !== void 0 ? _this$hot$getRowHeigh : defaultRowHeight;
      });
      return rowHeights;
    }
  });
  const totalPages = _classPrivateFieldGet(_calcStrategy, this).getTotalPages();
  _classPrivateFieldSet(_currentPage, this, clamp(_classPrivateFieldGet(_currentPage, this), 1, totalPages));
  if (renderableIndexes.length > 0) {
    const {
      startIndex,
      pageSize
    } = _classPrivateFieldGet(_calcStrategy, this).getState(_classPrivateFieldGet(_currentPage, this));
    renderableIndexes.splice(startIndex, pageSize);
  }
  if (renderableIndexes.length > 0) {
    this.hot.batchExecution(() => {
      renderableIndexes.forEach(index => _classPrivateFieldGet(_pagedRowsMap, this).setValueAtIndex(index, true));
    }, true);
  } else {
    this.hot.rowIndexMapper.updateCache(true);
  }
  _classPrivateFieldSet(_internalExecutionCall, this, false);
  const paginationData = this.getPaginationData();
  _classPrivateFieldGet(_ui, this).updateState({
    ...paginationData,
    totalRenderedRows: renderableRowsLength
  });
  if ((this.getSetting('showPageSize') || this.getSetting('showNavigation')) && paginationData.totalPages > 1) {
    _classPrivateFieldGet(_focusDetector, this).activate();
  } else {
    _classPrivateFieldGet(_focusDetector, this).deactivate();
  }
}
/**
 * Based on the external factors (like the scroll position of the table, size etc.) it computes
 * the need for the top border of the pagination UI container.
 *
 * @returns {boolean} Returns `true` if the pagination UI should have a top border, `false` otherwise.
 */
function _computeNeedsBorder() {
  if (!this.hot.view) {
    return true;
  }
  const {
    view
  } = this.hot;
  if (view.isVerticallyScrollableByWindow()) {
    return false;
  }
  if (view.hasHorizontalScroll() || view.getTableHeight() < view.getWorkspaceHeight()) {
    return true;
  }
  const {
    lastVisibleRowIndex
  } = this.getPaginationData();
  return view.getLastFullyVisibleRow() !== lastVisibleRowIndex;
}
/**
 * Called before the selection of columns or all table is made. It modifies the selection rows range
 * to the range of the current page.
 *
 * @param {CellCoords} from Starting cell coordinates.
 * @param {CellCoords} to Ending cell coordinates.
 */
function _onBeforeSelectAllRows(from, to) {
  const {
    firstVisibleRowIndex,
    lastVisibleRowIndex
  } = this.getPaginationData();
  if (_classPrivateFieldGet(_currentPage, this) > 1 || from.row >= 0) {
    from.row = firstVisibleRowIndex;
  }
  to.row = lastVisibleRowIndex;
}
/**
 * Called before the selection end is fired. It modifies the selection to the range of
 * the current page.
 *
 * @param {CellCoords} coords Ending cell coordinates.
 */
function _onBeforeSetRangeEnd(coords) {
  if (this.hot.selection.isSelectedByColumnHeader()) {
    const {
      lastVisibleRowIndex
    } = this.getPaginationData();
    coords.row = lastVisibleRowIndex;
  }
}
/**
 * The hook corrects the focus position (before drawing it) after the selection was made
 * (the visual coordinates was collected).
 */
function _onBeforeSelectionHighlightSet() {
  if (!this.hot.getSettings().navigableHeaders) {
    return;
  }
  const selectedRange = this.hot.getSelectedRangeLast();
  if (!selectedRange.isSingle()) {
    const {
      highlight
    } = selectedRange;
    highlight.row = clamp(highlight.row, selectedRange.getTopStartCorner().row, selectedRange.getBottomEndCorner().row);
  }
}
/**
 * Called before the paste operation is performed. It removes the rows that are not visible
 * from the pasted data.
 *
 * @param {Array} pastedData The data that was pasted.
 * @param {Array<{startRow: number, endRow: number}>} ranges The ranges of the pasted data.
 * @returns {boolean} Returns `false` to prevent the paste operation.
 */
function _onBeforePaste(pastedData, ranges) {
  const {
    firstVisibleRowIndex,
    lastVisibleRowIndex
  } = this.getPaginationData();
  if (firstVisibleRowIndex === -1 || lastVisibleRowIndex === -1) {
    return false;
  }
  ranges.forEach(_ref => {
    let {
      startRow
    } = _ref;
    if (pastedData.length === 0) {
      return;
    }
    const rowsToRemove = Math.min(pastedData.length - (lastVisibleRowIndex - startRow + 1), pastedData.length);
    pastedData.splice(0, rowsToRemove);
  });
}
/**
 * Called when the row height is modified. It adds 1px border top compensation for
 * the first row of the each page to make sure that the table's hider element
 * height is correctly calculated.
 *
 * @param {number | undefined} height Row height.
 * @param {number} row Visual row index.
 * @returns {number}
 */
function _onModifyRowHeight(height, row) {
  if (height === undefined || !_classPrivateFieldGet(_calcStrategy, this).getState(_classPrivateFieldGet(_currentPage, this))) {
    return;
  }
  const {
    firstVisibleRowIndex
  } = this.getPaginationData();
  if (row !== 0 && row === firstVisibleRowIndex) {
    height += 1; // 1px border top compensation for the first row of the page.
  }
  return height;
}
/**
 * Called after the view is rendered. It recalculates the pagination state only when
 * the `pageSize` is set to `'auto'`. In this case, the plugin will compute the
 * page size based on the viewport size and row heights for each render cycle to make sure
 * that each row resize, multiline cell value, or other factors that may affect the
 * rows height will be taken into account.
 */
function _onAfterViewRender() {
  if (_classPrivateFieldGet(_pageSize, this) !== 'auto' || _classPrivateFieldGet(_internalRenderCall, this)) {
    _classPrivateFieldSet(_internalRenderCall, this, false);
    return;
  }
  _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
  _classPrivateFieldSet(_internalRenderCall, this, true);
  // there is need to re-render the table as on the initial the engine returns incorrect
  // values about table and column header sizes.
  this.hot.view.adjustElementsSize();
  this.hot.render();
}
/**
 * Called after the rendering of the table is completed. It updates the width of
 * the pagination container to the same size as the table.
 */
function _onAfterRender() {
  const {
    view
  } = this.hot;
  const width = view.isHorizontallyScrollableByWindow() ? view.getTotalTableWidth() : view.getWorkspaceWidth();
  _classPrivateFieldGet(_ui, this).updateWidth(width).refreshBorderState();
}
/**
 * Called before the height of the table is changed. It adjusts the table height to fit the pagination container
 * in declared height.
 *
 * @param {number|string} height Table height.
 * @returns {string} Returns the new table height.
 */
function _onBeforeHeightChange(height) {
  if (this.getSetting('uiContainer')) {
    return height;
  }
  const isPixelValue = typeof height === 'number' || typeof height === 'string' && /^\d+$/.test(height) || typeof height === 'string' && height.endsWith('px');
  if (!isPixelValue) {
    return height;
  }
  const heightValue = typeof height === 'string' && height.endsWith('px') ? height : `${height}px`;
  return `calc(${heightValue} - ${_classPrivateFieldGet(_ui, this).getHeight()}px)`;
}
/**
 * Called after the initialization of the plugin. It computes the initial state of the pagination.
 */
function _onInit() {
  if (_classPrivateFieldGet(_pageSize, this) === 'auto') {
    return;
  }
  _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
}
/**
 * Called after the vertical scrolling of the table is completed. It refreshes
 * the border state of the pagination UI.
 */
function _onAfterScrollVertically() {
  _classPrivateFieldGet(_ui, this).refreshBorderState();
}
/**
 * Called after the language change. It recomputes the pagination state which updates the UI.
 */
function _onAfterLanguageChange() {
  _assertClassBrand(_Pagination_brand, this, _computeAndApplyState).call(this);
}
/**
 * Called after the theme is set. It updates the theme of the pagination container.
 *
 * @param {string | undefined} themeName The name of the theme to use.
 */
function _onAfterSetTheme(themeName) {
  _classPrivateFieldGet(_ui, this).updateTheme(themeName);
}
/**
 * Unfocuses the pagination and sets the active context for the shortcuts.
 */
function _unFocusPagination() {
  _classPrivateFieldGet(_focusDetector, this).activate();
  _classPrivateFieldGet(_focusController, this).clear();
  this.hot.unlisten();
  this.hot.getShortcutManager().setActiveContextName('grid');
}
/**
 * Called after the dialog is shown. It sets the active context for the shortcuts.
 */
function _onAfterDialogShow() {
  _classPrivateFieldGet(_focusDetector, this).deactivate();
}
/**
 * Called after the dialog is hidden. It sets the active context for the shortcuts.
 */
function _onAfterDialogHide() {
  _classPrivateFieldGet(_focusDetector, this).activate();
}